package util.sql;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import bean.Student;
import android.app.Application;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;


public class DbHelper extends SQLiteOpenHelper {
	private Class<?>[] classes = new Class[]{Student.class};
	private final static String DBNAME="DB.db";
	private final static int VERSION = 1;

	private DbHelper(Context context) {
		super(context, DBNAME, null, VERSION);
	}
	
	private static SQLiteDatabase db=null;
	
	public static SQLiteDatabase getDb(){
		return db;
	}
	
	public static void init(Application c){
		if(db==null){
			db= new DbHelper(c).getWritableDatabase();
		}
	}
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		for(Class<?> c : classes){
			db.execSQL(SqlUtil.getSqlForCreateTable(c));
		}
	}
	
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		
	}
	
	/**
	 * @param cursor
	 * @param c
	 */
	@SuppressWarnings("unchecked")
	public static <T> Object getItem(Cursor cursor, Class<T> c){
		T t = null;
		if(cursor.moveToFirst()){
			t = (T) SqlUtil.getInstance(cursor, c);
		}
		cursor.close();
		return t;
	}
	
	public static final <T>ArrayList <T> getItemList(Class<T> c, Cursor cursor){
		ArrayList<T> list = new ArrayList<T>();
		try {
			Field[] fields = c.getFields();
			HashMap<Field, Integer> indexMap = new HashMap<Field, Integer>();
			for(Field field : fields){
				indexMap.put(field, cursor.getColumnIndex(SqlUtil.getColumnName(field)));
			}
			while(cursor.moveToFirst()){
				@SuppressWarnings("unchecked")
				T t =  (T) SqlUtil.getInstance(cursor, c);
				if(null!=t){
					list.add(t);
				}
			}
		} catch (Exception e) {
			Log.exception(e);
		} 
		cursor.close();
		return list;
	}
	
	
	final private static String[] nullParams = new String[]{};
	public static <T> ArrayList<T> getList(Class<T> c, int limit){
		Cursor cursor = db.rawQuery("select * from "+SqlUtil.getTableName(c)+" limit "+limit, nullParams);
		return getItemList(c, cursor);
	}
	
	public static final <T> Object getItem(Object primaryKey, Class<T> c){
		Cursor cursor= db.rawQuery(SqlUtil.getSqlForSelect(primaryKey, c), nullParams);
		return getItem(cursor, c);
	}
	
	public static final void update(Object obj){
		if(null==obj){
			Log.error(DbHelper.class.getName()+":null value");
			return;
		}
		db.execSQL(SqlUtil.getSqlForUpdate(obj));
	}
	
	/**
	 * @param obj
	 */
	public static final void updateList(List<?> objs){
		if(objs.isEmpty()){
			return;
		}
		try{
			db.beginTransaction();
			for(Object obj : objs){
				db.execSQL(SqlUtil.getSqlForUpdate(obj));
			}
			db.setTransactionSuccessful();
		}catch(Exception e){
			Log.exception(e);
		}catch(Error e){
			Log.error(e);
		}finally{
			db.endTransaction();
		}
	}
	
	/**
	 * @param obj
	 */
	public static final void save(Object obj){
		if(null==obj){
			Log.error(DbHelper.class.getName()+":null value");
			return;
		}
		db.execSQL(SqlUtil.getSqlForInsert(obj));
	}
	/**
	 * @param obj
	 */
	public static final void saveList(List<?> objs){
		if(objs.isEmpty()){
			return;
		}
		try{
			db.beginTransaction();
			for(Object obj : objs){
				db.execSQL(SqlUtil.getSqlForInsert(obj));
			}
			db.setTransactionSuccessful();
		}catch(Exception e){
			Log.exception(e);
		}catch(Error e){
			Log.error(e);
		}finally{
			db.endTransaction();
		}
	}
	/**
	 * @param obj
	 */
	public static final void saveAsync(final List<Object> objs){
		new Thread(new Runnable(){
			@Override
			public void run() {
				save(objs);
			}
		}).start();
	}

	public static final void clear(Class<?> c){
		db.execSQL("delete from "+SqlUtil.getTableName(c));
	}
	
	public static final String getTable(Class<?> c){
		return SqlUtil.getTableName(c);
	}
	
	
	
}
